package com.yenlien.traceyun.plant.service;

import com.alibaba.fastjson.JSONObject;
import com.yenlien.traceyun.business.dao.BaseSoilEquipmentDao;
import com.yenlien.traceyun.business.dao.EquipmentDao;
import com.yenlien.traceyun.business.entity.BaseSoilEquipment;
import com.yenlien.traceyun.business.entity.Equipment;
import com.yenlien.traceyun.common.utils.HttpUtil;
import com.yenlien.traceyun.plant.controller.vo.DeviceHistoryDataVO;
import com.yenlien.traceyun.plant.controller.vo.XinFengXiangAndKeBai;
import com.yenlien.traceyun.plant.dao.KeBaiDao;
import com.yenlien.traceyun.plant.dao.XinFengXiangDao;
import com.yenlien.traceyun.plant.dock_device.kebai.KeBaiData;
import com.yenlien.traceyun.plant.dock_device.kebai.KeBaiGetData;
import com.yenlien.traceyun.plant.dock_device.xinfengxiang.XinFengXiang;
import com.yenlien.traceyun.webase.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import static com.yenlien.traceyun.plant.dock_device.DevState.EQU_MANUFACTURER_KB;
import static com.yenlien.traceyun.plant.dock_device.DevState.EQU_MANUFACTURER_XFX;

/**
 * @author jialong
 * @date 2021/03/31
 * @description: 新风向逻辑层
 **/
@Slf4j
@Service
public class DockDeviceService {

    @Autowired
    private EquipmentDao equipmentDao;

    @Autowired
    private BaseSoilEquipmentDao baseSoilEquipmentDao;

    @Value("${xinFengXiang.url}")
    private String url;                         // 新风向获取数据的接口

    @Value("${keBai.getAllDataByUserUrl}")
    private String getAllDataByUserUrl;         // 科百获取数据的接口

    @Autowired
    private KeBaiGetData keBaiGetData;

    @Autowired
    private KeBaiDao keBaiDao;

    @Autowired
    private XinFengXiangDao xinFengXiangDao;


    // 科百数据的 传感器类型编码 字典
    public final static Map<String, String> SensorType = new HashMap();

    /**
     * @param baseSoilId
     * @return
     */
    public Object getNowData(String baseSoilId) {
        List<Equipment> equipmentList = equipmentDao.getEquipmentByBaseSOilId(baseSoilId);
        if (equipmentList != null && equipmentList.size() > 0) {
            List<XinFengXiangAndKeBai> results = new ArrayList<>();             // 返回的结果

            // 把设备按厂商分成新风向和科百
            List<Equipment> keBaiDeviceList = new ArrayList<>();
            List<Equipment> xinFengXiangDeviceList = new ArrayList<>();
            for (Equipment equipment : equipmentList) {
                if (EQU_MANUFACTURER_XFX.equals(equipment.getManufacturer())) {
                    xinFengXiangDeviceList.add(equipment);
                } else if (EQU_MANUFACTURER_KB.equals(equipment.getManufacturer())) {
                    keBaiDeviceList.add(equipment);
                }
            }
            // 先获取科百的数据
            // 构造地块与设备的对应关系
            List<BaseSoilEquipment> equipmentBaseSoilList = new ArrayList<>();
            for (Equipment equipment : keBaiDeviceList) {
                BaseSoilEquipment baseSoilEquipment = new BaseSoilEquipment(equipment.getId(), baseSoilId);
                equipmentBaseSoilList.add(baseSoilEquipment);
            }
            // 获取我们平台下的科百设备的数据
            List<KeBaiData> bind = keBaiGetData.bind(keBaiDeviceList, keBaiGetData.getAllDataByUser(keBaiGetData.userName, keBaiGetData.password), equipmentBaseSoilList);
            // 把科百数据放入到结果集中
            for (KeBaiData keBai : bind) {
                results.add(
                        new XinFengXiangAndKeBai("2", keBai.getEquipmentId(), keBai.getNodecode(), baseSoilId, keBai.getEquipmentName(), keBai.getCompanyId(),
                                keBai.getNodename(), keBai.getSensorname(), keBai.getStationname(), keBai.getStationcode(), keBai.getThattime(), keBai.getUnit(), keBai.getSenval(),
                                getTypeByCode(keBai.getSensortype()), keBai.getSensorcode(), new Date())
                );
            }
            // 获取新风向数据
            xinFengXiangDeviceList.forEach(equipment -> {
                JSONObject result = JSONObject.parseObject(HttpUtil.getDataFromUrl(url + equipment.getSerial()));     // 获取数据并解析
                if (result == null) {
                    log.error("请求新风向数据接口的结果为null, 接口路径为:{}", url + equipment.getSerial());
                }
                if ("200".equals(result.get("statusCode")) && "success".equals(result.get("message"))) {
                    List<XinFengXiangAndKeBai> xinFengXiangList = JSONObject.parseArray(result.getJSONArray("entity").toJSONString(), XinFengXiangAndKeBai.class);
                    if (xinFengXiangList == null || xinFengXiangList.size() == 0) {
                        log.error("该序列号对应的设备在新风向平台不存在, 序列号: {}", equipment.getSerial());
                    }
                    for (XinFengXiangAndKeBai xinFengXiang : xinFengXiangList) {
                        xinFengXiang.setDataType("1");
                        xinFengXiang.setDeviceId(result.get("deviceId").toString());
                        xinFengXiang.setEquipmentId(equipment.getId());
                        xinFengXiang.setBaseSoilId(baseSoilId);
                        xinFengXiang.setEquipmentName(equipment.getName());
                        xinFengXiang.setCompanyId(equipment.getCompanyId());
                    }
                    results.addAll(xinFengXiangList);
                } else {
                    log.error("请求不成功, 返回结果: {}", result.toString());
                }
            });
            return results;
        } else {
            log.error("该地块 {} 没有对应的设备", baseSoilId);
            return new ArrayList<>();
        }
    }

    /**
     * 据点的ID获取该点绑定设备3天前至现在的数据,每天各一条
     *
     * @param baseSoilId
     * @return
     */
    public Object findList3Days(String baseSoilId) {
        List<XinFengXiangAndKeBai> results = new ArrayList<>();
        List<Equipment> equipment = equipmentDao.getEquipmentByBaseSOilId(baseSoilId);
        if (equipment.size() == 0 || equipment == null) {
            throw new BusinessException("该点没有对应的设备");
        }
        List<KeBaiData> keBaiDataList = new ArrayList<>();
        List<XinFengXiang> xinFengXiangs = new ArrayList<>();
        if (EQU_MANUFACTURER_KB.equals(equipment.get(0).getManufacturer())) {
            keBaiDataList = keBaiDao.findList3Days(baseSoilId);
        } else if (EQU_MANUFACTURER_XFX.equals(equipment.get(0).getManufacturer())) {
            xinFengXiangs = xinFengXiangDao.findList3Days(baseSoilId);
        } else {
            throw new BusinessException("该设备不属于新风向或科百厂商, 无法获取气象数据, 设备ID:{}", equipment.get(0).getId());
        }
        // 组装科百数据
        for (KeBaiData keBai : keBaiDataList) {
            results.add(
                    new XinFengXiangAndKeBai("2", keBai.getEquipmentId(), keBai.getNodecode(), baseSoilId, keBai.getEquipmentName(), keBai.getCompanyId(),
                            keBai.getNodename(), keBai.getSensorname(), keBai.getStationname(), keBai.getStationcode(), keBai.getThattime(), keBai.getUnit(), keBai.getSenval(),
                            getTypeByCode(keBai.getSensortype()), keBai.getSensorcode(), new Date())
            );
        }

        // 组装新风向数据
        for (XinFengXiang xinFengXiang : xinFengXiangs) {
            results.add(
                    new XinFengXiangAndKeBai("1", xinFengXiang.getEquipmentId(), xinFengXiang.getDeviceId(), xinFengXiang.getBaseSoilId(), xinFengXiang.getEquipmentName(),
                            xinFengXiang.getCompanyId(), xinFengXiang.getDateTime(), xinFengXiang.getEUnit(), xinFengXiang.getEValue(), xinFengXiang.getEKey(), xinFengXiang.getEName(),
                            xinFengXiang.getENum(), xinFengXiang.getCreateTime())
            );
        }
        return results;
    }


    public List<Equipment> getUrl(String baseSoilId) {
        return equipmentDao.getEquipmentByBaseSOilId(baseSoilId);
    }


    public Object getHistoryData(Date startTime, Date endTime, String equId) {
        ArrayList<DeviceHistoryDataVO> historyDataVOS = new ArrayList<>();
        List<KeBaiData> keBaiDatas = getKeBaiDatas(startTime, endTime, equId);
        if (keBaiDatas != null && keBaiDatas.size() > 0) {
            // 按传感器类型分组
            Map<String, List<KeBaiData>> sensorTypeMap = keBaiDatas.stream().collect(Collectors.groupingBy(KeBaiData::getSensorname));
            for (Map.Entry<String, List<KeBaiData>> entry : sensorTypeMap.entrySet()) {
                DeviceHistoryDataVO deviceHistoryDataVO = new DeviceHistoryDataVO();
                deviceHistoryDataVO.setSensorType(entry.getKey());
                final List<KeBaiData> value = entry.getValue();
                deviceHistoryDataVO.setDates(value.stream().map(KeBaiData::getCreateTime).collect(Collectors.toList()));
                deviceHistoryDataVO.setValues(value.stream().map(KeBaiData::getSenval).collect(Collectors.toList()));
                historyDataVOS.add(deviceHistoryDataVO);
            }
        } else {
            List<XinFengXiang> xinFengXiangs = getXinFengXiangs(startTime, endTime, equId);
            if (xinFengXiangs == null || xinFengXiangs.size() == 0) {
                // 该设备没有数据
                return historyDataVOS;
            }
            Map<String, List<XinFengXiang>> sensorTypeMap = xinFengXiangs.stream().collect(Collectors.groupingBy(XinFengXiang::getEName));
            for (Map.Entry<String, List<XinFengXiang>> entry : sensorTypeMap.entrySet()) {
                DeviceHistoryDataVO deviceHistoryDataVO = new DeviceHistoryDataVO();
                deviceHistoryDataVO.setSensorType(entry.getKey());
                final List<XinFengXiang> value = entry.getValue();
                deviceHistoryDataVO.setDates(value.stream().map(XinFengXiang::getCreateTime).collect(Collectors.toList()));
                deviceHistoryDataVO.setValues(value.stream().map(XinFengXiang::getEValue).collect(Collectors.toList()));
                historyDataVOS.add(deviceHistoryDataVO);
            }
        }
        return historyDataVOS;
    }


    public Object getEquByMassifId(String massifId, String type) {
        if(StringUtils.isBlank(type)){
            return baseSoilEquipmentDao.getEquipmentByMassifId(massifId);
        }else {
            return baseSoilEquipmentDao.getEquipmentByMassifIdType(massifId, type);
        }
    }


    public List<KeBaiData> getKeBaiDatas(Date startTime, Date endTime, String equId) {
        if (startTime == null && endTime == null) {
            return keBaiDao.findByEquipmentId(equId);
        } else if (startTime != null && endTime != null) {
            return keBaiDao.findHistoryData(equId, startTime, endTime);
        }
        return new ArrayList<>();
//        Sort sort = Sort.by(Sort.Direction.ASC,"createTime");
//        return keBaiDao.findAll((Root<KeBaiData> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
//            //构造查询条件
//            List<Predicate> list = new ArrayList<Predicate>();
//            Path<String> equipmentId = root.get("equipmentId");
//            list.add(cb.equal(equipmentId, equId));
//            if(startTime != null && endTime != null){
//                Path<Date> createTime = root.get("createTime");
//                list.add(cb.between(createTime, startTime, endTime));
//            }
//            Predicate[] p = new Predicate[list.size()];
//            return cb.and(list.toArray(p));
//        }, sort);
    }

    public List<XinFengXiang> getXinFengXiangs(Date startTime, Date endTime, String equId) {
        if (startTime == null && endTime == null) {
            return xinFengXiangDao.findByEquipmentId(equId);
        } else if (startTime != null && endTime != null) {
            return xinFengXiangDao.findHistoryData(equId, startTime, endTime);
        }
        return new ArrayList<>();
//        Sort sort = Sort.by(Sort.Direction.ASC,"createTime");
//        return xinFengXiangDao.findAll((Root<XinFengXiang> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
//            //构造查询条件
//            List<Predicate> list = new ArrayList<Predicate>();
//            Path<String> equipmentId = root.get("equipmentId");
//            list.add(cb.equal(equipmentId, equId));
//            if(startTime != null && endTime != null){
//                Path<Date> createTime = root.get("createTime");
//                list.add(cb.between(createTime, startTime, endTime));
//            }
//            Predicate[] p = new Predicate[list.size()];
//            return cb.and(list.toArray(p));
//        }, sort);
    }


    /**
     * 根据code取得对应的类型
     *
     * @param code
     * @return
     */
    public String getTypeByCode(String code) {
        if (SensorType == null || SensorType.size() == 0) {
            generateSensorType();
        }
        String dirValue = SensorType.get(code);
        if (StringUtils.isBlank(dirValue)) {
            dirValue = "未知";
        }
        return dirValue;
    }

    /**
     * 生成科百传感器类型字典
     */
    public void generateSensorType() {
        if (SensorType == null || SensorType.size() == 0) {
            SensorType.put("1", "空气温度");
            SensorType.put("2", "相对湿度");
            SensorType.put("3", "土壤温度");
            SensorType.put("5", "降雨量");
            SensorType.put("6", "风速");
            SensorType.put("8", "光照强度");
            SensorType.put("10", "大气压");
            SensorType.put("12", "叶面湿度");
            SensorType.put("16", "风向");
            SensorType.put("17", "露点");
            SensorType.put("19", "流量开关");
            SensorType.put("25", "土壤水分");
            SensorType.put("40", "流量");
            SensorType.put("42", "水势MPS");
            SensorType.put("43", "土壤EC值");
            SensorType.put("44", "介质GS3");
            SensorType.put("46", "紫外线指数");
            SensorType.put("47", "太阳能电池板");
            SensorType.put("49", "土壤PH值");
            SensorType.put("51", "水位");
            SensorType.put("56", "CO2");
            SensorType.put("59", "PH3");
            SensorType.put("63", "植物有效辐射");
            SensorType.put("65", "信号");
            SensorType.put("66", "可入肺颗粒物空气");
            SensorType.put("67", "PM10空气");
            SensorType.put("72", "NO2");
            SensorType.put("73", "SO2");
            SensorType.put("74", "果实直径");
            SensorType.put("130", "茎秆微变");
            SensorType.put("699", "土壤电导率");
            SensorType.put("716", "太阳全辐射");
            SensorType.put("717", "热通量");
            SensorType.put("718", "累计流量");
        }
    }


}
